package com.vhall.component.service.data.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.dao.anchors.AnchorManageMapper;
import com.vhall.component.dao.data.AccountForDataMapper;
import com.vhall.component.dao.livecolumn.LiveColumnMapper;
import com.vhall.component.dao.praise.RoomLikeMapper;
import com.vhall.component.dao.record.RecordAttendsMapper;
import com.vhall.component.dao.record.RecordMapper;
import com.vhall.component.dao.room.*;
import com.vhall.component.entity.account.AccountEntity;
import com.vhall.component.entity.anchors.AnchorManageEntity;
import com.vhall.component.entity.chat.vo.ChatConsoleListPage;
import com.vhall.component.entity.chat.vo.ChatConsoleListReqVO;
import com.vhall.component.entity.chat.vo.ChatConsoleListRspVO;
import com.vhall.component.entity.data.enums.DataStatusEnum;
import com.vhall.component.entity.data.enums.DurationDistributionEnum;
import com.vhall.component.entity.data.enums.SelectTimeIntervalOptionsEnum;
import com.vhall.component.entity.data.enums.SortTypeEnum;
import com.vhall.component.entity.data.vo.*;
import com.vhall.component.entity.interactive.vo.QuestionConsoleLogReqVO;
import com.vhall.component.entity.interactive.vo.QuestionConsoleLogRspVO;
import com.vhall.component.entity.interactive.vo.QuestionLogPage;
import com.vhall.component.entity.page.vo.PageVO;
import com.vhall.component.entity.rbac.enums.RoleTypeEnum;
import com.vhall.component.entity.record.RecordAttendsEntity;
import com.vhall.component.entity.record.RecordEntity;
import com.vhall.component.entity.record.enums.LiveStreamingTypeEnum;
import com.vhall.component.entity.room.RoomAttendsEntity;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.entity.room.entity.AnchorRoomLkEntity;
import com.vhall.component.entity.room.entity.RoomForwardEntity;
import com.vhall.component.entity.room.entity.RoomStatsExpansion;
import com.vhall.component.entity.room.entity.RoomsEntity;
import com.vhall.component.entity.room.enums.*;
import com.vhall.component.entity.subject.enums.StatusEnum;
import com.vhall.component.entity.tag.vo.PageChannelListReqVO;
import com.vhall.component.entity.tag.vo.PageChannelListRspVO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.CollectionUtils;
import com.vhall.component.framework.common.utils.DateTimeUtils;
import com.vhall.component.plugin.common.constant.ConstStr;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.enums.AccountType;
import com.vhall.component.plugin.common.enums.DeleteStatusEnum;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.plugin.common.utils.BeanCopyUtil;
import com.vhall.component.plugin.core.enums.SendMessageTypeEnum;
import com.vhall.component.plugin.core.service.PaasService;
import com.vhall.component.service.chat.ChatConsoleService;
import com.vhall.component.service.data.DataService;
import com.vhall.component.service.guosen.ExternalLiveStatsService;
import com.vhall.component.service.interactive.QuestionConsoleService;
import com.vhall.component.service.room.RoomInnerService;
import com.vhall.component.service.tag.PageChannelService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Preconditions;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.vhall.component.plugin.common.constant.RedisKey.CACHE_SELECTEDVIDEOLIST_GETPVCOUNTFROMSTATICS;

/**
 * 用户表服务实现类
 *
 * @author kainan.li
 * @date 2021-04-06 19:01:15
 */
@Slf4j
@Service
public class DataServiceImpl implements DataService {

    @Autowired
    private AccountForDataMapper accountForDataMapper;

    @Autowired
    private RoomInnerService roomInnerService;

    @Resource
    private PageChannelService pageChannelService;

    @Autowired
    private ChatConsoleService chatConsoleService;

    @Autowired
    private RecordMapper recordMapper;

    @Autowired
    private RoomAttendsMapper roomAttendsMapper;


    @Autowired
    private QuestionConsoleService questionConsoleService;

    @Resource
    private RoomMapper roomMapper;

    @Resource
    private AnchorManageMapper anchorManageMapper;

    @Resource
    private AnchorRoomLkMapper anchorRoomLkMapper;

    @Resource
    private RoomForwardMapper roomForwardMapper;

    @Resource
    private RoomLikeMapper roomLikeMapper;

    @Resource
    private RecordAttendsMapper recordAttendsMapper;
    @Resource
    private PaasService paasService;
    @Resource
    private RoomStatsExpansionMapper roomStatsExpansionMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private LiveColumnMapper liveColumnMapper;
    @Resource
    private AnchorRoomRelationMapper anchorRoomRelationMapper;
    @Resource
    private ExternalLiveStatsService externalLiveStatsService;
    @Override
    public BasicStatisticsInfoVO getBasicStatisticsInfo(UserParamVO reqVO) {
        String status = reqVO.getStatus();
        UserBasicStatisticsRspVO ubsrv = accountForDataMapper.getBasicStatisticsInfo(reqVO);
        int uvCount = ubsrv.getUvCount();
        int pvCount = (ubsrv.getPvCount() != null && ubsrv.getPvCount() > 0) ? ubsrv.getPvCount() : 0;
        int watchDuration = ubsrv.getTotalDuration();
        Integer avgPvCount = 0;
        Integer avgWatchDuration = 0;

        UserBasicStatisticsRspVO ubsrvVod = accountForDataMapper.getVodBasicStatisticsInfo(reqVO);
        uvCount += ubsrvVod.getUvCount();
        pvCount += (ubsrvVod.getPvCount() != null && ubsrvVod.getPvCount() > 0) ? ubsrvVod.getPvCount() : 0;

        // 这里增加从saas迁移过来的数据
        RoomsEntity roomsEntity = getRoomsEntity(reqVO);
//        UV-历史迁移数据的 uv
        Integer totalNumberOfViewers = roomsEntity.getTotalNumberOfViewers();
        uvCount += totalNumberOfViewers;
//        PV历史迁移数据的 pv
        Integer totalNumberOfViews = roomsEntity.getTotalNumberOfViews();
        pvCount += totalNumberOfViews;

        watchDuration += ubsrvVod.getTotalDuration();
        if (uvCount != 0) {
            double aa = Math.ceil((double) pvCount / (double) uvCount);
            double bb = Math.ceil((double) watchDuration / (double) uvCount);
            avgPvCount = Convert.toInt(aa);
            avgWatchDuration = Convert.toInt(bb);
        }
        UserBasicStatisticsRspVO ub = new UserBasicStatisticsRspVO();
        ub.setUvCount(uvCount);
//        ub.setPvCount(pvCount);
        ub.setTotalDuration(watchDuration);
        ub.setAvgPvCount(avgPvCount);
        ub.setAvgWatchDuration(avgWatchDuration);

        // pv数据
        assemblyPvData(reqVO, ub, null);
        ub.setWatchPvApp(ub.getWatchPvApp()+totalNumberOfViews);
        ub.setWatchPvH5AddApp(ub.getWatchPvH5AddApp()+totalNumberOfViews);
        // 聊天数量
        assemblyNumberOfChats(reqVO, ub);

        // 互动时长
//        assemblyInteractionDuration(reqVO, ub);

        // 完播率
//        assemblyCompletionRate(reqVO, ub, null);

        // 获取问卷数据
//        assemblyQuestion(reqVO, ub);

        // 预约数据
        Integer ubsrvReservationNum = accountForDataMapper.getNumberOfReservation(reqVO);
        ub.setNumberOfReservation(ubsrvReservationNum);

        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        if (roomInfo.getLiveType().equals(LiveRoomTypeEnum.ON_DEMAND.getType())) {
            //  app 参与人数
            assemblyAppParticipants(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            //  h5 参与人数
            assemblyH5Participants(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            // 转发量
            assemblyForwardNum(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            // 点赞量
            assemblyLikeNum(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());
        }


        BigDecimal liveFlow = accountForDataMapper.getUserLiveFlow(reqVO);
        BigDecimal vodFlow = accountForDataMapper.getUserVodFlow(reqVO);
        BigDecimal totalFlow = BigDecimal.valueOf(0);
        if (liveFlow != null) {
            totalFlow = totalFlow.add(liveFlow);
        }
        if (vodFlow != null) {
            totalFlow = totalFlow.add(vodFlow);
        }
        ub.setTotalFlow(totalFlow);

        BigDecimal vodStorage = accountForDataMapper.getUserVodStorage(reqVO);
        ub.setTotalStorage(vodStorage != null ? vodStorage : BigDecimal.valueOf(0));
        Integer maxPv = accountForDataMapper.getUserMaxPv(reqVO);
        ub.setMaxPv(maxPv != null ? maxPv : 0);
        ub.setUvPreviewPage(accountForDataMapper.getUvPreviewPage(reqVO));
        Integer ilId = reqVO.getIlId();
        Integer externalChannelViewCount = externalLiveStatsService.getCacheLiveExternalChannelViewCount(ilId);
        ub.setExternalChannelViewCount(externalChannelViewCount);
        return getJson(ub, status, reqVO);

    }


    private RoomsEntity getRoomsEntity(UserParamVO reqVO) {
        LambdaQueryWrapper<RoomsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomsEntity::getRoomId, reqVO.getRoomId());
        wrapper.ge(RoomsEntity::getMigrateAt, reqVO.getStartTime());
        wrapper.le(RoomsEntity::getMigrateAt, reqVO.getEndTime());
        RoomsEntity roomsEntity = roomMapper.selectOne(wrapper);
        if (roomsEntity == null) {
            RoomsEntity entity = new RoomsEntity();
            entity.setTotalNumberOfViewers(0);
            entity.setTotalNumberOfViews(0);
            return entity;
        }
        return roomsEntity;
    }


//    /**
//     * 互动时长
//     * 只有直播数据才有
//     */
//    private void assemblyInteractionDuration(UserParamVO reqVO, UserBasicStatisticsRspVO ub) {
//        UserParamVO paramVO = new UserParamVO();
//        BeanCopyUtil.copy(reqVO, paramVO);
//        paramVO.setType(2);
//        UserBasicStatisticsRspVO basicStatisticsInfo = accountForDataMapper.getBasicStatisticsInfo(paramVO);
//        ub.setInteractionDuration(basicStatisticsInfo.getTotalDuration() == null ? 0 : basicStatisticsInfo.getTotalDuration());
//    }

    private void assemblyNumberOfChats(UserParamVO reqVO, UserBasicStatisticsRspVO ub) {
        ChatConsoleListReqVO chatConsoleListReqVO = new ChatConsoleListReqVO();
        // 防止前端不传递分页参数，在这里进行设置。
        if (chatConsoleListReqVO.getPage() == null) {
            chatConsoleListReqVO.setPage(1);
        }
        if (chatConsoleListReqVO.getPageSize() == null) {
            chatConsoleListReqVO.setPageSize(20);
        }

        chatConsoleListReqVO.setBeginTime(reqVO.getStartTime());
        chatConsoleListReqVO.setEndTime(reqVO.getEndTime());

        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        if (null == roomInfo) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }

        ChatConsoleListPage<ChatConsoleListRspVO> list = chatConsoleService.list(chatConsoleListReqVO, roomInfo);
        ub.setNumberOfChats(list != null && list.getTotal() > 0 ? list.getTotal() : 0);
    }

    private void assemblyQuestion(UserParamVO reqVO, UserBasicStatisticsRspVO ub) {
        QuestionConsoleLogReqVO req = new QuestionConsoleLogReqVO();
        req.setBeginTime(reqVO.getStartTime());
        req.setEndTime(reqVO.getEndTime());
        if (req.getPage() == null || "0".equals(String.valueOf(req.getPage()))) {
            req.setPage(1);
        }
        if (req.getPageSize() == null) {
            req.setPageSize(10);
        }
        if (StringUtils.isNotBlank(req.getEndTime())) {
            String endTime = req.getEndTime();
            if (endTime.contains(ConstStr.TIME_ZERO)) {
                endTime = endTime.replace(ConstStr.TIME_ZERO, ConstStr.TIME_FULL);
            } else {
                endTime = endTime + " " + ConstStr.TIME_FULL;
            }
            req.setEndTime(endTime);
        }
        QuestionLogPage<QuestionConsoleLogRspVO> questionLog = questionConsoleService.getQuestionLog(req);

        int questionnaire = 0;
        int answerSheet = 0;

        if (questionLog != null && CollectionUtils.isNotEmpty(questionLog.getData())) {
            List<QuestionConsoleLogRspVO> data = questionLog.getData();
            questionnaire = data.size();
            for (QuestionConsoleLogRspVO datum : data) {
                answerSheet = answerSheet + datum.getAnswerCount();
            }
        }

        ub.setQuestionnaire(questionnaire);
        ub.setAnswerSheet(answerSheet);
    }

    private void assemblyCompletionRate(UserParamVO reqVO, UserBasicStatisticsRspVO ub, Integer liveStreamingType) {

        Integer completionRate = 0;
        Integer completionRateLive = 0;
        Integer completionRateBack = 0;

        // 获取房间信息
        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        if (StringUtils.isNotBlank(roomInfo.getRecordId()) && Objects.equals(roomInfo.getPlaybackStatus(), RoomAuditStatusEnum.APPROVED.getAuditStatus())) {

            // 获取视频信息
            RecordEntity recordEntity = getRecordEntity(roomInfo);
            // 获取视频 时长/秒
            Integer duration = recordEntity.getDuration();

            if (liveStreamingType == null) {
                // 获取观看直播的信息
                completionRateLive = getLiveRate(reqVO, completionRateLive, recordEntity, duration);

                // 获取观看回放的完播率
                completionRateBack = getBackRate(reqVO, completionRateBack, recordEntity, duration);

                BigDecimal add = new BigDecimal(completionRateLive).add(new BigDecimal(completionRateBack));
                completionRate = add.divide(new BigDecimal("2"), 2, RoundingMode.HALF_UP).intValue();
            } else if (liveStreamingType.equals(LiveStreamingTypeEnum.LIVE_BROADCAST.getValue())) {
                //  获取观看直播的信息
                completionRate = getLiveRate(reqVO, completionRateLive, recordEntity, duration);
            } else if (liveStreamingType.equals(LiveStreamingTypeEnum.PLAYBACK.getValue())) {
                //  获取观看回放的完播率
                completionRate = getBackRate(reqVO, completionRateBack, recordEntity, duration);

            }

        }


        ub.setCompletionRate(completionRate);
    }

    private RecordEntity getRecordEntity(RoomsEntityDTO roomInfo) {
        LambdaQueryWrapper<RecordEntity> queryWrapper = Wrappers.lambdaQuery();
//        queryWrapper.eq(RecordEntity::getRoomId, roomInfo.getRoomId());
        queryWrapper.eq(RecordEntity::getVodId, roomInfo.getRecordId());
        queryWrapper.eq(RecordEntity::getStatus, DeleteStatusEnum.NO_DELETE.getStatus());
        queryWrapper.last("limit 1");
        List<RecordEntity> recordEntities = recordMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(recordEntities)) {
            return recordEntities.get(0);
        }
        throw new BusinessException(MessageFormat.format("回放:【{0}】查询异常", roomInfo.getRecordId()));
    }

    private Integer getBackRate(UserParamVO reqVO, Integer completionRateBack, RecordEntity recordEntity, Integer duration) {

        List<RecordAttendsEntity> recordAttendsEntities = getRecordAttendsEntities(reqVO, recordEntity);

        if (CollectionUtils.isNotEmpty(recordAttendsEntities)) {
            Map<Integer, List<RecordAttendsEntity>> userMap = recordAttendsEntities.stream().collect(Collectors.groupingBy(RecordAttendsEntity::getWatchAccountId));
            // 获取总人数
            int userTotal = userMap.size();

            // 所有人观看最长时间累加
            int sumMaxDuration = 0;

            // 获取单个人观看最长数据
            for (Map.Entry<Integer, List<RecordAttendsEntity>> integerListEntry : userMap.entrySet()) {
                RecordAttendsEntity attendsEntity = integerListEntry.getValue().stream().max(Comparator.comparing(RecordAttendsEntity::getDuration)).get();
                int personMaxDuration = attendsEntity.getDuration() > duration ? duration : attendsEntity.getDuration();
                sumMaxDuration = sumMaxDuration + personMaxDuration;
            }

            BigDecimal bigDecimal = new BigDecimal(sumMaxDuration).divide(new BigDecimal(userTotal).multiply(new BigDecimal(duration)), 2, RoundingMode.HALF_UP);
            completionRateBack = bigDecimal.multiply(new BigDecimal("100")).intValue();
        }
        return completionRateBack;
    }

    private List<RecordAttendsEntity> getRecordAttendsEntities(UserParamVO reqVO, RecordEntity recordEntity) {

        LambdaQueryWrapper<RecordAttendsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RecordAttendsEntity::getIlId, recordEntity.getIlId());
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RecordAttendsEntity::getCreatedAt, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RecordAttendsEntity::getCreatedAt, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        return recordAttendsMapper.selectList(wrapper);
    }

    private Integer getLiveRate(UserParamVO reqVO, Integer completionRate, RecordEntity recordEntity, Integer duration) {

        List<RoomAttendsEntity> roomAttendsEntities = getRoomAttendsEntities(reqVO, recordEntity);

        if (CollectionUtils.isNotEmpty(roomAttendsEntities)) {
            Map<Integer, List<RoomAttendsEntity>> userMap = roomAttendsEntities.stream().collect(Collectors.groupingBy(RoomAttendsEntity::getWatchAccountId));
            // 获取总人数
            int userTotal = userMap.size();

            // 所有人观看最长时间累加
            int sumMaxDuration = 0;

            // 获取单个人观看最长数据
            for (Map.Entry<Integer, List<RoomAttendsEntity>> integerListEntry : userMap.entrySet()) {
                RoomAttendsEntity roomAttendsEntity = integerListEntry.getValue().stream().max(Comparator.comparing(RoomAttendsEntity::getDuration)).get();
                int personMaxDuration = roomAttendsEntity.getDuration() > duration ? duration : roomAttendsEntity.getDuration();
                sumMaxDuration = sumMaxDuration + personMaxDuration;
            }

            BigDecimal bigDecimal = new BigDecimal(sumMaxDuration).divide(new BigDecimal(userTotal).multiply(new BigDecimal(duration)), 2, RoundingMode.HALF_UP);
            completionRate = bigDecimal.multiply(new BigDecimal("100")).intValue();
        }
        return completionRate;
    }

    private List<RoomAttendsEntity> getRoomAttendsEntities(UserParamVO reqVO, RecordEntity recordEntity) {
        LambdaQueryWrapper<RoomAttendsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RoomAttendsEntity::getIlId, recordEntity.getIlId());
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RoomAttendsEntity::getCreatedAt, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RoomAttendsEntity::getCreatedAt, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        return roomAttendsMapper.selectList(wrapper);
    }

    /**
     * @param reqVO
     * @param ub
     * @param liveStreamingType LiveStreamingTypeEnum  LIVE_BROADCAST(0, "直播"),  PLAYBACK(1, "回放"),
     */
    private void assemblyPvData(UserParamVO reqVO, UserBasicStatisticsRspVO ub, Integer liveStreamingType) {


        int watchPvApp = 0;
        int watchPvH5 = 0;
        int watchPvWechat = 0;


        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        if (LiveStreamingTypeEnum.LIVE_BROADCAST.getValue().equals(liveStreamingType)) {
            reqVO.setIlId(roomInfo.getIlId());
            watchPvApp = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.IOSSDK.getValue(), TerminalEnum.ANDROIDSDK.getValue()));
            watchPvH5 = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.JSWAP.getValue()));
            watchPvWechat = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.WECHAT.getValue()));

        } else if (LiveStreamingTypeEnum.PLAYBACK.getValue().equals(liveStreamingType)) {
            watchPvApp = getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.IOSSDK.getValue(), TerminalEnum.ANDROIDSDK.getValue()));
            watchPvH5 = getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.JSWAP.getValue()));
            watchPvWechat = getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.WECHAT.getValue()));
        } else {
            reqVO.setIlId(roomInfo.getIlId());
            watchPvApp = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.IOSSDK.getValue(), TerminalEnum.ANDROIDSDK.getValue()));
            watchPvH5 = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.JSWAP.getValue()));
            watchPvWechat = getRoomAttendsPv(reqVO, Arrays.asList(TerminalEnum.WECHAT.getValue()));

            watchPvApp = watchPvApp + getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.IOSSDK.getValue(), TerminalEnum.ANDROIDSDK.getValue()));
            watchPvH5 = watchPvH5 + getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.JSWAP.getValue()));
            watchPvWechat = watchPvWechat + getRecordAttendsPv(reqVO, Arrays.asList(TerminalEnum.WECHAT.getValue()));

        }
        ub.setWatchPvWechat(watchPvWechat);
        ub.setWatchPvH5(watchPvH5 + watchPvWechat);
        ub.setWatchPvApp(watchPvApp);
        ub.setWatchPvH5AddApp(watchPvWechat + watchPvH5 + watchPvApp);
    }

    private int getRecordAttendsPv(UserParamVO reqVO, List<Integer> iOSAPP) {
        LambdaQueryWrapper<RecordAttendsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.in(StringUtils.isNotBlank(reqVO.getRoomId()), RecordAttendsEntity::getRoomId, reqVO.getRoomId());
        wrapper.in(RecordAttendsEntity::getTerminal, iOSAPP);
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RecordAttendsEntity::getCreatedAt, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RecordAttendsEntity::getCreatedAt, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        return recordAttendsMapper.selectList(wrapper).size();

    }

    private int getRoomAttendsPv(UserParamVO reqVO, List<Integer> list) {
        LambdaQueryWrapper<RoomAttendsEntity> wrapper = Wrappers.lambdaQuery();
        if (reqVO.getIlId() != null) {
            wrapper.eq(reqVO.getIlId() != null, RoomAttendsEntity::getIlId, reqVO.getIlId());
        } else if (CollectionUtils.isNotEmpty(reqVO.getIlIdList())) {
            wrapper.in(RoomAttendsEntity::getIlId, reqVO.getIlIdList());
        }

        wrapper.in(CollectionUtils.isNotEmpty(list), RoomAttendsEntity::getTerminal, list);
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RoomAttendsEntity::getStartTime, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RoomAttendsEntity::getStartTime, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        return roomAttendsMapper.selectCount(wrapper);

    }

    private BasicStatisticsInfoVO getJson(UserBasicStatisticsRspVO ubsrv, String status, UserParamVO reqVO) {
        Integer ilId = reqVO.getIlId();

        BasicStatisticsInfoVO jo = new BasicStatisticsInfoVO();

        jo.setLiveUv(BaseDataVO.builder().stat(ubsrv.getUvCount() == null ? 0 : ubsrv.getUvCount()).unit("人").export("uv").build());
        jo.setLivePv(BaseDataVO.builder().stat(ubsrv.getPvCount() == null ? 0 : ubsrv.getPvCount()).unit("次").export("pv").build());
        jo.setWatchTime(BaseDataVO.builder().stat(ubsrv.getTotalDuration() == null ? 0 : ubsrv.getTotalDuration()).unit("分钟").export("").build());

        BaseDataVO avgWatchTimeJo = new BaseDataVO();
        //1 全部
        if ("1".equals(status)) {
            if (ilId == null) {
                jo.setLiveFlow(BaseDataVO.builder().stat(ubsrv.getTotalFlow() == null ? 0 : ubsrv.getTotalFlow().intValue()).unit("MB").export("").build());
                jo.setRecordStorage(BaseDataVO.builder().stat(ubsrv.getTotalStorage() == null ? 0 : ubsrv.getTotalStorage().intValue()).unit("MB").export("").build());
            }

            jo.setMaxConcurrent(BaseDataVO.builder().stat(ubsrv.getMaxPv() == null ? 0 : ubsrv.getMaxPv()).unit("人").export("").build());

            avgWatchTimeJo = BaseDataVO.builder().stat(ubsrv.getAvgWatchDuration() == null ? 0 : ubsrv.getAvgWatchDuration()).unit("分钟").export("").build();
            jo.setNumberOfChats(BaseDataVO.builder().export("number_of_chats").stat(ubsrv.getNumberOfChats()).unit("").build());
//            jo.setInteractionDuration(BaseDataVO.builder().export("").stat(ubsrv.getInteractionDuration()).unit("").build());

            jo.setAppParticipants(BaseDataVO.builder().export("").stat(ubsrv.getAppParticipants() == null ? 0 : ubsrv.getAppParticipants()).unit("").build());
            jo.setH5Participants(BaseDataVO.builder().export("").stat(ubsrv.getH5Participants() == null ? 0 : ubsrv.getH5Participants()).unit("").build());
            jo.setForwardNum(BaseDataVO.builder().export("").stat(ubsrv.getForwardNum() == null ? 0 : ubsrv.getForwardNum()).unit("").build());
            jo.setLikeNum(BaseDataVO.builder().export("").stat(ubsrv.getLikeNum() == null ? 0 : ubsrv.getLikeNum()).unit("").build());
            jo.setNumberOfReservation(BaseDataVO.builder().export("").stat(ubsrv.getNumberOfReservation() == null ? 0 : ubsrv.getNumberOfReservation()).unit("次").export("number_of_reservation").build());
            jo.setUvPreviewPage(BaseDataVO.builder().stat(Optional.ofNullable(ubsrv.getUvPreviewPage()).orElse(0 )).unit("").export("uv_preview_page").build());
            jo.setExternalChannelViewCount(BaseDataVO.builder().stat(Optional.ofNullable(ubsrv.getExternalChannelViewCount()).orElse(0 )).unit("").export("").build());
        } else if ("2".equals(status)) {
            //2直播中

            jo.setLivingDuration(BaseDataVO.builder().stat(ubsrv.getLivingDuration() == null ? 0 : ubsrv.getLivingDuration()).unit("分钟").export("").build());
            jo.setMaxConcurrent(BaseDataVO.builder().stat(ubsrv.getMaxPv() == null ? 0 : ubsrv.getMaxPv()).unit("人").export("").build());


            avgWatchTimeJo = BaseDataVO.builder().stat(ubsrv.getAvgWatchDuration() == null ? 0 : ubsrv.getAvgWatchDuration()).unit("分钟").export("").build();
//            jo.setNumberOfChats(BaseDataVO.builder().export("number_of_chats").stat(ubsrv.getNumberOfChats()).unit("").build());
//            jo.setInteractionDuration(BaseDataVO.builder().export("").stat(ubsrv.getInteractionDuration()).unit("").build());

        } else if ("3".equals(status)) {
            //3直播回放
            jo.setVideoTime(BaseDataVO.builder().stat(ubsrv.getVideoTotalTime() == null ? 0 : ubsrv.getVideoTotalTime()).unit("分钟").export("").build());

            avgWatchTimeJo = BaseDataVO.builder().stat(ubsrv.getAvgWatchDuration() == null ? 0 : ubsrv.getAvgWatchDuration()).unit("分钟").export("").build();
//            jo.setInteractionDuration(BaseDataVO.builder().export("").stat(0).unit("").build());

            jo.setAppParticipants(BaseDataVO.builder().export("").stat(ubsrv.getAppParticipants() == null ? 0 : ubsrv.getAppParticipants()).unit("").build());
            jo.setH5Participants(BaseDataVO.builder().export("").stat(ubsrv.getH5Participants() == null ? 0 : ubsrv.getH5Participants()).unit("").build());
            jo.setForwardNum(BaseDataVO.builder().export("").stat(ubsrv.getForwardNum() == null ? 0 : ubsrv.getForwardNum()).unit("").build());
            jo.setLikeNum(BaseDataVO.builder().export("").stat(ubsrv.getLikeNum() == null ? 0 : ubsrv.getLikeNum()).unit("").build());
        }

        jo.setAvgWatchTime(avgWatchTimeJo);
        jo.setAvgLivePv(BaseDataVO.builder().stat(ubsrv.getAvgPvCount() == null ? 0 : ubsrv.getAvgPvCount()).unit("次").export("").build());
        jo.setWatchPvH5AddApp(BaseDataVO.builder().export("watch_pv_h5_app").stat(ubsrv.getWatchPvH5AddApp()).unit("").build());
        jo.setWatchPvH5(BaseDataVO.builder().export("").stat(ubsrv.getWatchPvH5()).unit("").build());
        jo.setWatchPvApp(BaseDataVO.builder().export("").stat(ubsrv.getWatchPvApp()).unit("").build());
        jo.setWatchPvWechat(BaseDataVO.builder().export("").stat(ubsrv.getWatchPvWechat()).unit("").build());
        jo.setCompletionRate(BaseDataVO.builder().export("").stat(ubsrv.getCompletionRate()).statStr(ubsrv.getCompletionRate() == null ? "" : ubsrv.getCompletionRate().toString() + "%").unit("%").build());
        jo.setQuestionnaire(BaseDataVO.builder().export("").stat(ubsrv.getQuestionnaire()).unit("").build());
        jo.setAnswerSheet(BaseDataVO.builder().export("").stat(ubsrv.getAnswerSheet()).unit("").build());

        return jo;
    }

    @Override
    public List<UserWatchPvRspVO> getUserWatchPvInfo(UserParamVO reqVO) {
        return accountForDataMapper.getUserWatchPvInfo(reqVO);
    }

    @Override
    public BasicStatisticsInfoVO getLiveBasicStatisticsInfo(UserParamVO reqVO) {
        UserBasicStatisticsRspVO ubsrv = accountForDataMapper.getBasicStatisticsInfo(reqVO);

        // 这里增加从saas迁移过来的数据
        RoomsEntity roomsEntity = getRoomsEntity(reqVO);
        ubsrv.setUvCount(ubsrv.getUvCount() + roomsEntity.getTotalNumberOfViewers());
        ubsrv.setPvCount(ubsrv.getPvCount() + roomsEntity.getTotalNumberOfViews());

        Integer avgPvCount = (ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ?
                Convert.toInt(Math.ceil(ubsrv.getPvCount().doubleValue() / ubsrv.getUvCount().doubleValue())) : 0;
        Integer avgWatchDuration = (ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ?
                Convert.toInt(Math.ceil(ubsrv.getTotalDuration().doubleValue() / ubsrv.getUvCount().doubleValue())) : 0;
        ubsrv.setAvgPvCount(avgPvCount);
        ubsrv.setAvgWatchDuration(avgWatchDuration);
        String status = reqVO.getStatus();
        Integer maxPv = accountForDataMapper.getUserMaxPv(reqVO);
        //Integer livingDuration = accountForDataMapper.liveDuration(reqVO);
        //从点播中获取直播时长数据
        Integer livingDuration = accountForDataMapper.liveDurationFromRecord(reqVO);
        ubsrv.setLivingDuration(livingDuration);
        ubsrv.setMaxPv(maxPv != null ? maxPv : 0);
        if (ubsrv.getTotalDuration() == null) {
            ubsrv.setTotalDuration(0);
        }

        // pv数据
        assemblyPvData(reqVO, ubsrv, LiveStreamingTypeEnum.LIVE_BROADCAST.getValue());

        // 聊天数量
//        assemblyNumberOfChats(reqVO, ubsrv);

        // 互动时长
//        assemblyInteractionDuration(reqVO, ubsrv);

        // 完播率
        assemblyCompletionRate(reqVO, ubsrv, LiveStreamingTypeEnum.LIVE_BROADCAST.getValue());

        // 获取问卷数据
//        assemblyQuestion(reqVO, ubsrv);

        return getJson(ubsrv, status, reqVO);
    }

    @Override
    public BasicStatisticsInfoVO getVodBasicStatisticsInfo(UserParamVO reqVO) {
        String status = reqVO.getStatus();
        UserBasicStatisticsRspVO ubsrv = accountForDataMapper.getVodBasicStatisticsInfo(reqVO);

        // 这里增加从saas迁移过来的数据
        RoomsEntity roomsEntity = getRoomsEntity(reqVO);
        ubsrv.setUvCount(ubsrv.getUvCount() == null ? roomsEntity.getTotalNumberOfViewers() : ubsrv.getUvCount() + roomsEntity.getTotalNumberOfViewers());
        ubsrv.setPvCount(ubsrv.getPvCount() == null ? roomsEntity.getTotalNumberOfViews() : ubsrv.getPvCount() + roomsEntity.getTotalNumberOfViews());


        if (ubsrv.getTotalDuration() == null) {
            ubsrv.setTotalDuration(0);
        }
        Integer avgPvCount = (ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ?
                Convert.toInt(Math.ceil(ubsrv.getPvCount().doubleValue() / ubsrv.getUvCount().doubleValue())) : 0;
        Integer avgWatchDuration = (ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ?
                Convert.toInt(Math.ceil(ubsrv.getTotalDuration().doubleValue() / ubsrv.getUvCount().doubleValue())) : 0;
        ubsrv.setAvgPvCount(avgPvCount);
        ubsrv.setAvgWatchDuration(avgWatchDuration);
        Integer videoTotalTime = accountForDataMapper.getVodTotalTime(reqVO);
        ubsrv.setVideoTotalTime(videoTotalTime);

        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());

        if (roomInfo.getLiveType().equals(LiveRoomTypeEnum.ON_DEMAND.getType())) {
            //  app 参与人数
            assemblyAppParticipants(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            //  h5 参与人数
            assemblyH5Participants(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            // 转发量
            assemblyForwardNum(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

            // 点赞量
            assemblyLikeNum(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());
        }


        // pv数据
        assemblyPvData(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

        // 完播率
        assemblyCompletionRate(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());

        return getJson(ubsrv, status, reqVO);
    }

    private void assemblyLikeNum(UserParamVO reqVO, UserBasicStatisticsRspVO ubsrv, Integer value) {
        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        ubsrv.setLikeNum(roomInfo.getLike());
    }

    private void assemblyForwardNum(UserParamVO reqVO, UserBasicStatisticsRspVO ubsrv, Integer value) {
        LambdaQueryWrapper<RoomForwardEntity> where = Wrappers.lambdaQuery();
        where.eq(RoomForwardEntity::getRoomId, reqVO.getRoomId());
        List<RoomForwardEntity> roomForwardEntities = roomForwardMapper.selectList(where);
        ubsrv.setForwardNum(roomForwardEntities.size());
    }

    private void assemblyH5Participants(UserParamVO reqVO, UserBasicStatisticsRspVO ubsrv, Integer value) {
        reqVO.setTerminals(Collections.singletonList(10));
        UserBasicStatisticsRspVO ubsrvVod = accountForDataMapper.getVodBasicStatisticsInfo(reqVO);
        ubsrv.setH5Participants(ubsrvVod.getUvCount());
    }

    private void assemblyAppParticipants(UserParamVO reqVO, UserBasicStatisticsRspVO ubsrv, Integer value) {
        reqVO.setTerminals(Arrays.asList(4, 5));
        UserBasicStatisticsRspVO ubsrvVod = accountForDataMapper.getVodBasicStatisticsInfo(reqVO);

        ubsrv.setAppParticipants(ubsrvVod.getUvCount());
    }


    @Override
    public List<UserDeviceRspVO> getDeviceInfo(UserParamVO reqVO) {

        // pv数据
        UserBasicStatisticsRspVO ubsrv = new UserBasicStatisticsRspVO();
        assemblyPvData(reqVO, ubsrv, null);


        List<UserDeviceRspVO> result = new ArrayList<>();

        UserDeviceRspVO app = new UserDeviceRspVO();
        app.setName("APP观看");
        app.setValue(ubsrv.getWatchPvApp());

        UserDeviceRspVO h5 = new UserDeviceRspVO();
        h5.setName("H5观看");
        h5.setValue(ubsrv.getWatchPvH5());

        result.add(app);
        result.add(h5);
        return result;
    }

    @Override
    public List<UserDeviceRspVO> getLiveDeviceInfo(UserParamVO reqVO) {

        // pv数据
        UserBasicStatisticsRspVO ubsrv = new UserBasicStatisticsRspVO();
        assemblyPvData(reqVO, ubsrv, LiveStreamingTypeEnum.LIVE_BROADCAST.getValue());


        List<UserDeviceRspVO> result = new ArrayList<>();

        UserDeviceRspVO app = new UserDeviceRspVO();
        app.setName("APP观看");
        app.setValue(ubsrv.getWatchPvApp());

        UserDeviceRspVO h5 = new UserDeviceRspVO();
        h5.setName("H5观看");
        h5.setValue(ubsrv.getWatchPvH5());

        result.add(app);
        result.add(h5);

        return result;


    }

    @Override
    public List<UserDeviceRspVO> getVodDeviceInfo(UserParamVO reqVO) {

        // pv数据
        UserBasicStatisticsRspVO ubsrv = new UserBasicStatisticsRspVO();
        assemblyPvData(reqVO, ubsrv, LiveStreamingTypeEnum.PLAYBACK.getValue());


        List<UserDeviceRspVO> result = new ArrayList<>();

        UserDeviceRspVO app = new UserDeviceRspVO();
        app.setName("APP观看");
        app.setValue(ubsrv.getWatchPvApp());

        UserDeviceRspVO h5 = new UserDeviceRspVO();
        h5.setName("H5观看");
        h5.setValue(ubsrv.getWatchPvH5());

        result.add(app);
        result.add(h5);

        return result;

    }

    @Override
    public List<UserLiveWatchUvRspVO> getLiveUserWatchUvInfo(UserParamVO reqVO) {
        List<UserLiveWatchUvRspVO> liveList = accountForDataMapper.getLiveUserWatchUvInfo(reqVO);
        List<UserLiveWatchUvRspVO> inavList = accountForDataMapper.getInavUserWatchUvInfo(reqVO);

        if (CollectionUtils.isNotEmpty(inavList)) {
            liveList.addAll(inavList);
        }
        Map<String, List<UserLiveWatchUvRspVO>> collect = liveList.stream().collect(Collectors.groupingBy(UserLiveWatchUvRspVO::getDatetime));

        List<UserLiveWatchUvRspVO> list = new ArrayList<>();
        for (Map.Entry<String, List<UserLiveWatchUvRspVO>> entry : collect.entrySet()) {
            UserLiveWatchUvRspVO ulwu = new UserLiveWatchUvRspVO();
            ulwu.setDatetime(entry.getKey());
            List<UserLiveWatchUvRspVO> value = entry.getValue();

            int duration = 0;
            int pvNum = 0;
            int uvNum = 0;

            for (UserLiveWatchUvRspVO ulw : value) {
                duration += ulw.getDuration();
                pvNum += ulw.getPvNum();
                uvNum += ulw.getUvNum();
            }
            ulwu.setDuration(duration);
            ulwu.setPvNum(pvNum);
            ulwu.setUvNum(uvNum);
            list.add(ulwu);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
        list.sort((x, y) -> {
            try {
                return Long.compare(simpleDateFormat.parse(x.getDatetime()).getTime(), simpleDateFormat.parse(y.getDatetime()).getTime());
            } catch (ParseException e) {
                throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
            }
        });
        return list;
    }

    @Override
    public List<UserLiveWatchUvRspVO> getVodUserWatchUvInfo(UserParamVO reqVO) {
        List<UserLiveWatchUvRspVO> vodList = accountForDataMapper.getVodUserWatchUvInfo(reqVO);
        Map<String, List<UserLiveWatchUvRspVO>> collect = vodList.stream().collect(Collectors.groupingBy(UserLiveWatchUvRspVO::getDatetime));

        List<UserLiveWatchUvRspVO> list = new ArrayList<>();
        for (Map.Entry<String, List<UserLiveWatchUvRspVO>> entry : collect.entrySet()) {
            UserLiveWatchUvRspVO ulwu = new UserLiveWatchUvRspVO();
            ulwu.setDatetime(entry.getKey());
            List<UserLiveWatchUvRspVO> value = entry.getValue();

            int duration = 0;
            int pvNum = 0;
            int uvNum = 0;

            for (UserLiveWatchUvRspVO ulw : value) {
                duration += ulw.getDuration();
                pvNum += ulw.getPvNum();
                uvNum += ulw.getUvNum();
            }
            ulwu.setDuration(duration);
            ulwu.setPvNum(pvNum);
            ulwu.setUvNum(uvNum);
            list.add(ulwu);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
        list.sort((x, y) -> {
            try {
                return Long.compare(simpleDateFormat.parse(x.getDatetime()).getTime(), simpleDateFormat.parse(y.getDatetime()).getTime());
            } catch (ParseException e) {
                throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
            }
        });
        return list;
    }


    @Override
    public List<UserLiveWatchUvRspVO> getUserWatchUvInfo(UserParamVO reqVO) {
        List<UserLiveWatchUvRspVO> liveList = accountForDataMapper.getLiveUserWatchUvInfo(reqVO);
        List<UserLiveWatchUvRspVO> vodList = accountForDataMapper.getVodUserWatchUvInfo(reqVO);
        List<UserLiveWatchUvRspVO> inavList = accountForDataMapper.getInavUserWatchUvInfo(reqVO);

        if (CollectionUtils.isNotEmpty(vodList)) {
            liveList.addAll(vodList);
        }

        if (CollectionUtils.isNotEmpty(inavList)) {
            liveList.addAll(inavList);
        }
        Map<String, List<UserLiveWatchUvRspVO>> collect = liveList.stream().collect(Collectors.groupingBy(UserLiveWatchUvRspVO::getDatetime));

        List<UserLiveWatchUvRspVO> list = new ArrayList<>();
        for (Map.Entry<String, List<UserLiveWatchUvRspVO>> entry : collect.entrySet()) {
            UserLiveWatchUvRspVO ulwu = new UserLiveWatchUvRspVO();
            ulwu.setDatetime(entry.getKey());
            List<UserLiveWatchUvRspVO> value = entry.getValue();

            int duration = 0;
            int pvNum = 0;
            int uvNum = 0;

            for (UserLiveWatchUvRspVO ulw : value) {
                duration += ulw.getDuration();
                pvNum += ulw.getPvNum();
                uvNum += ulw.getUvNum();
            }
            ulwu.setDuration(duration);
            ulwu.setPvNum(pvNum);
            ulwu.setUvNum(uvNum);
            list.add(ulwu);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
        list.sort((x, y) -> {
            try {
                return Long.compare(simpleDateFormat.parse(x.getDatetime()).getTime(), simpleDateFormat.parse(y.getDatetime()).getTime());
            } catch (ParseException e) {
                throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
            }
        });
        return list;
    }

    @Override
    public List<UserProvinceRspVO> getProvinceInfo(UserParamVO reqVO) {
        List<UserProvinceRspVO> live = StringUtils.isNotEmpty(reqVO.getCtry()) ? accountForDataMapper.getLiveProvinceInfoByProvince(reqVO) : accountForDataMapper.getLiveProvinceInfoByCountry(reqVO);
        List<UserProvinceRspVO> vod = StringUtils.isNotEmpty(reqVO.getCtry()) ? accountForDataMapper.getVodProvinceInfoByProvince(reqVO) : accountForDataMapper.getVodProvinceInfoByCountry(reqVO);
        Map<String, Integer> stringIntegerHashMap = new HashMap<>(16);
        if (CollectionUtils.isNotEmpty(live)) {
            stringIntegerHashMap = live.stream().collect(Collectors.toMap(UserProvinceRspVO::getName, UserProvinceRspVO::getValue));
        }
        if (CollectionUtils.isNotEmpty(vod)) {
            for (UserProvinceRspVO userProvinceRspVO : vod) {
                final Integer orDefault = stringIntegerHashMap.getOrDefault(userProvinceRspVO.getName(), 0);
                stringIntegerHashMap.put(userProvinceRspVO.getName(), orDefault + userProvinceRspVO.getValue());
            }
        }
        final ArrayList<UserProvinceRspVO> userProvinceRspVOS = new ArrayList<>();
        for (Map.Entry<String, Integer> map : stringIntegerHashMap.entrySet()) {
            userProvinceRspVOS.add(new UserProvinceRspVO(map.getKey(), map.getValue()));
        }
        return userProvinceRspVOS;
    }

    @Override
    public List<UserProvinceRspVO> getLiveProvinceInfo(UserParamVO reqVO) {
        return StringUtils.isNotEmpty(reqVO.getCtry()) ? accountForDataMapper.getLiveProvinceInfoByProvince(reqVO) : accountForDataMapper.getLiveProvinceInfoByCountry(reqVO);
    }

    @Override
    public List<UserProvinceRspVO> getVodProvinceInfo(UserParamVO reqVO) {
        return StringUtils.isNotEmpty(reqVO.getCtry()) ? accountForDataMapper.getVodProvinceInfoByProvince(reqVO) : accountForDataMapper.getVodProvinceInfoByCountry(reqVO);
    }

    @Override
    public BasicStatisticsInfoVO getBasicInfo(UserParamVO reqVO) {
        reqVO.setEndTime(setReqEndTime(reqVO.getEndTime()));
        String status = reqVO.getStatus();
        BasicStatisticsInfoVO udrv = new BasicStatisticsInfoVO();
        if (StringUtils.isBlank(reqVO.getRoomId())) {
            reqVO.setIlId(null);
        } else {
            RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
            reqVO.setIlId(roomInfo == null ? null : roomInfo.getIlId());
        }
        if ("1".equals(status)) {
            //全部
            udrv = getBasicStatisticsInfo(reqVO);
        } else if ("2".equals(status)) {
            //直播中
            roomCheck(reqVO);
            udrv = getLiveBasicStatisticsInfo(reqVO);
        } else if ("3".equals(status)) {
            //直播回放
            roomCheck(reqVO);
            udrv = getVodBasicStatisticsInfo(reqVO);
        }
        return udrv;
    }

    @Override
    public List<DpWatchTimeTopRspVO> getDpWatchTimeTop(UserParamVO reqVO) {

        validateSixTime(reqVO);
        String status = reqVO.getStatus();
        reqVO.setEndTime(setReqEndTime(reqVO.getEndTime()));
        DataStatusEnum dataStatusEnum = DataStatusEnum.parse(status);
        List<DpWatchTimeTopRspVO> resultVO = null;
        boolean allFlag = false;
        switch (dataStatusEnum) {
            case ALL:
                resultVO = getAllDpWatchTimeTop(reqVO);
                allFlag = true;
                break;
            case LIVE_STREAMING:
                resultVO = getLiveStreamDpWatchTimeTop(reqVO);
                break;
            case LIVE_PLAYBACK:
                resultVO = getLiveBackDpWatchTimeTop(reqVO);
                break;
            default:
                break;
        }

        return assemblyResult(resultVO, allFlag);
    }

    /**
     * 12个月时间校验
     */
    private void validateSixTime(UserParamVO reqVO) {
        LocalDateTime start = DateUtil.parseLocalDateTime(reqVO.getStartTime(), DatePattern.NORM_DATE_PATTERN);
        LocalDateTime end = DateUtil.parseLocalDateTime(reqVO.getEndTime(), DatePattern.NORM_DATE_PATTERN);

        long between = DateTimeUtils.betweenTwoTime(start, end, ChronoUnit.MONTHS);
        if (between > 12) {
            throw new BusinessException(BizErrorCode.BIZ_DATA_OVER_LONG_ERROR);
        }
    }

    /**
     * 直播观看数据（按频道）
     */
    @Override
    public List<PageChannelListRspVO> getDpChannelAvgViewDuration(UserParamVO reqVO) {
        validateSixTime(reqVO);
        // 获取频道那棵树
        List<PageChannelListRspVO> pageChannelListRspVos = pageChannelService.listInfo(new PageChannelListReqVO());

        if (CollectionUtils.isNotEmpty(pageChannelListRspVos)) {

            if (reqVO.getSortType() == null || reqVO.getSortType() == 4) {
                pageChannelListRspVos = pageChannelListRspVos.stream().sorted(Comparator.comparing(PageChannelListRspVO::getLiveNumber)).collect(Collectors.toList());
            } else {
                pageChannelListRspVos = pageChannelListRspVos.stream().sorted(Comparator.comparing(PageChannelListRspVO::getLiveNumber).reversed()).collect(Collectors.toList());
            }
        }


        return pageChannelListRspVos;


    }


    private List<RoomsEntity> getRoomsMap(UserParamVO reqVO, List<PageChannelListRspVO> children) {
        LambdaQueryWrapper<RoomsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.ge(RoomsEntity::getBeginLiveTime, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(RoomsEntity::getBeginLiveTime, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        wrapper.eq(RoomsEntity::getAuditStatus, RoomAuditStatusEnum.APPROVED.getAuditStatus());
        wrapper.orderByAsc(RoomsEntity::getBeginLiveTime);
        return roomMapper.selectList(wrapper);

    }

    /**
     * 直播观看数据（按讲师）
     */
    @Override
    public List<DpLecturerAvgViewDurationRspVO> getDpLecturerAvgViewDuration(UserParamVO reqVO) {
        validateSixTime(reqVO);
        // 获取所有讲师
        LambdaQueryWrapper<AnchorManageEntity> where = Wrappers.lambdaQuery();
        where.eq(AnchorManageEntity::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
        List<AnchorManageEntity> anchorManageEntities = anchorManageMapper.selectList(where);
        List<DpLecturerAvgViewDurationRspVO> rspVOS = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(anchorManageEntities)) {
            assemblyVos(anchorManageEntities, rspVOS);
            rspVOS = getRspVOS(reqVO, rspVOS);
        }
        return rspVOS;
    }


    private List<DpLecturerAvgViewDurationRspVO> getRspVOS(UserParamVO reqVO, List<DpLecturerAvgViewDurationRspVO> rspVos) {


        // 获取指定时间 所有开播的房间信息
        List<RoomsEntity> roomsEntityList = getRoomsMap(reqVO, new ArrayList<>());
        // 这些房间对应的讲师信息
        Map<Integer, List<AnchorRoomLkEntity>> listMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(roomsEntityList)) {
            LambdaQueryWrapper<AnchorRoomLkEntity> where2 = Wrappers.lambdaQuery();
            where2.in(AnchorRoomLkEntity::getAnchorId, rspVos.stream().map(DpLecturerAvgViewDurationRspVO::getAnchorId).collect(Collectors.toList()));
            where2.in(AnchorRoomLkEntity::getRoomId, roomsEntityList.stream().map(RoomsEntity::getRoomId).collect(Collectors.toList()));
            where2.eq(AnchorRoomLkEntity::getDeleted, DeleteStatusEnum.NO_DELETE.getStatus());
            List<AnchorRoomLkEntity> anchorRoomLkEntities = anchorRoomLkMapper.selectList(where2);
            listMap = anchorRoomLkEntities.stream().collect(Collectors.groupingBy(AnchorRoomLkEntity::getAnchorId));
        }


        for (DpLecturerAvgViewDurationRspVO rspVO : rspVos) {

            if (listMap.get(rspVO.getAnchorId()) == null || CollectionUtils.isEmpty(listMap.get(rspVO.getAnchorId()))) {
                continue;
            }

            // 当前讲师关联的信息
            List<AnchorRoomLkEntity> lkEntities = listMap.get(rspVO.getAnchorId());

            int liveNumber = CollectionUtils.isEmpty(lkEntities) ? 0 : lkEntities.size();

            List<String> roomIdList = lkEntities.stream().map(AnchorRoomLkEntity::getRoomId).collect(Collectors.toList());
            LambdaQueryWrapper<RoomsEntity> roomWrapper = Wrappers.lambdaQuery();
            roomWrapper.in(RoomsEntity::getRoomId, roomIdList);
            List<RoomsEntity> entityList = roomMapper.selectList(roomWrapper);


            // 获取自建pv数据
            reqVO.setIlIdList(entityList.stream().map(RoomsEntity::getIlId).collect(Collectors.toList()));
            int liveStreamingNumTemp = getRoomAttendsPv(reqVO, null);


            UserParamVO userParamVO = new UserParamVO();
            userParamVO.setStartTime(reqVO.getStartTime());
            userParamVO.setEndTime(reqVO.getEndTime());
            userParamVO.setIlIdList(entityList.stream().map(RoomsEntity::getIlId).collect(Collectors.toList()));
            UserBasicStatisticsRspVO ubsrv = accountForDataMapper.getBasicStatisticsInfo(userParamVO);
            int pvCount = (ubsrv.getPvCount() != null && ubsrv.getPvCount() > 0) ? ubsrv.getPvCount() : 0;
            int uvCount = (ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ? ubsrv.getUvCount() : 0;


            UserBasicStatisticsRspVO ubsrvVod = accountForDataMapper.getVodBasicStatisticsInfo(userParamVO);
            pvCount += (ubsrvVod.getPvCount() != null && ubsrvVod.getPvCount() > 0) ? ubsrvVod.getPvCount() : 0;
            uvCount += (ubsrvVod.getUvCount() != null && ubsrvVod.getUvCount() > 0) ? ubsrvVod.getUvCount() : 0;

            rspVO.setLiveNumber(liveNumber);
            rspVO.setTotalNumberOfViewers(uvCount);
            rspVO.setTotalViews(pvCount);

            rspVO.setLiveStreamingViewersNum((ubsrv.getUvCount() != null && ubsrv.getUvCount() > 0) ? ubsrv.getUvCount() : 0);
            rspVO.setLiveStreamingNum(liveStreamingNumTemp);

        }

        if (reqVO.getSortType() == null || reqVO.getSortType() == 4) {
            rspVos = rspVos.stream().sorted(Comparator.comparing(DpLecturerAvgViewDurationRspVO::getLiveNumber)).collect(Collectors.toList());
        } else {
            rspVos = rspVos.stream().sorted(Comparator.comparing(DpLecturerAvgViewDurationRspVO::getLiveNumber).reversed()).collect(Collectors.toList());
        }
        return rspVos;
    }

    private void assemblyVos(List<AnchorManageEntity> anchorManageEntities, List<DpLecturerAvgViewDurationRspVO> rspVos) {
        for (AnchorManageEntity e : anchorManageEntities) {
            DpLecturerAvgViewDurationRspVO dpLecturerAvgViewDurationRspVO = new DpLecturerAvgViewDurationRspVO();
            BeanCopyUtil.copy(e, dpLecturerAvgViewDurationRspVO);
            dpLecturerAvgViewDurationRspVO.setAnchorName(e.getRealName());
            rspVos.add(dpLecturerAvgViewDurationRspVO);
        }
    }

    @Override
    public List<UserViewDurationDistributionRspVO> getDpUserViewDurationDistribution(UserParamVO reqVO) {

        validateSixTime(reqVO);
        Token token = TokenThreadLocal.getToken();
        String orgCode = token.getOrgCode();
        if (!Objects.equals(RoleTypeEnum.PLATFORM_LEVEL.getValue(),token.getRoleType())) {
            reqVO.setOrgCode(orgCode);
        }
        String status = reqVO.getStatus();
        DataStatusEnum dataStatusEnum = DataStatusEnum.parse(status);
        List<UserViewDurationDistributionRspVO> resultVO = null;
        boolean allFlag = false;
        switch (dataStatusEnum) {
            case ALL:
                resultVO = getAllDurationDistribution(reqVO);
                allFlag = true;
                break;
            case LIVE_STREAMING:
                resultVO = getLiveStreamDurationDistribution(reqVO);
                break;
            case LIVE_PLAYBACK:
                resultVO = getLiveBackDurationDistribution(reqVO);
                break;
            default:
                break;
        }

        return assemblyDurationDistributionResult(resultVO, allFlag);

    }

    private List<UserViewDurationDistributionRspVO> assemblyDurationDistributionResult(List<UserViewDurationDistributionRspVO> resultVO, boolean allFlag) {
        if (allFlag) {
            return resultVO;
        }

        List<UserViewDurationDistributionRspVO> result = new ArrayList<>();
        Map<Integer, List<UserViewDurationDistributionRspVO>> listMap = resultVO.stream().collect(Collectors.groupingBy(UserViewDurationDistributionRspVO::getKey));
        for (int i = 0; i < 9; i++) {
            List<UserViewDurationDistributionRspVO> live = CollectionUtils.isEmpty(listMap.get(i)) ? new ArrayList<>() : listMap.get(i);
            UserViewDurationDistributionRspVO rspVO = new UserViewDurationDistributionRspVO();
            rspVO.setKey(i);
            rspVO.setNum(CollectionUtils.isEmpty(live) ? 0 : live.get(0).getNum());
            result.add(rspVO);

        }

        return result;
    }

    /**
     * 回放
     */
    private List<UserViewDurationDistributionRspVO> getLiveBackDurationDistribution(UserParamVO reqVO) {

        LambdaQueryWrapper<RecordAttendsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RecordAttendsEntity::getCreatedAt, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RecordAttendsEntity::getCreatedAt, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        List<RecordAttendsEntity> recordStatsEntities = recordAttendsMapper.selectList(wrapper);

        String orgCode = reqVO.getOrgCode();
        String existsSql = " select rooms.il_id from rooms where rooms.il_id=record_attends.il_id and rooms.org_code='"+orgCode+"' ";
        wrapper.exists(StringUtils.isNotEmpty(orgCode), existsSql);
        List<UserViewDurationDistributionRspVO> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(recordStatsEntities)) {
            Map<Integer, List<RecordAttendsEntity>> listMap = recordStatsEntities.stream().collect(Collectors.groupingBy(e -> DurationDistributionEnum.getKey(e.getDuration())));
            for (Map.Entry<Integer, List<RecordAttendsEntity>> integerListEntry : listMap.entrySet()) {
                UserViewDurationDistributionRspVO userViewDurationDistributionRspVO = new UserViewDurationDistributionRspVO();
                userViewDurationDistributionRspVO.setKey(integerListEntry.getKey());
                userViewDurationDistributionRspVO.setNum(integerListEntry.getValue().size());
                result.add(userViewDurationDistributionRspVO);
            }
        }

        return result;

    }

    /**
     * 直播
     */
    private List<UserViewDurationDistributionRspVO> getLiveStreamDurationDistribution(UserParamVO reqVO) {

        LambdaQueryWrapper<RoomAttendsEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.ge(StringUtils.isNotEmpty(reqVO.getStartTime()), RoomAttendsEntity::getCreatedAt, reqVO.getStartTime() + " " + ConstStr.TIME_ZERO);
        wrapper.le(StringUtils.isNotEmpty(reqVO.getEndTime()), RoomAttendsEntity::getCreatedAt, reqVO.getEndTime() + " " + ConstStr.TIME_FULL);
        List<RoomAttendsEntity> roomAttendsEntities = roomAttendsMapper.selectList(wrapper);
        List<UserViewDurationDistributionRspVO> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roomAttendsEntities)) {
            Map<Integer, List<RoomAttendsEntity>> listMap = roomAttendsEntities.stream().collect(Collectors.groupingBy(this::makeKey));
            for (Map.Entry<Integer, List<RoomAttendsEntity>> integerListEntry : listMap.entrySet()) {
                UserViewDurationDistributionRspVO userViewDurationDistributionRspVO = new UserViewDurationDistributionRspVO();
                userViewDurationDistributionRspVO.setKey(integerListEntry.getKey());
                userViewDurationDistributionRspVO.setNum(integerListEntry.getValue().size());
                result.add(userViewDurationDistributionRspVO);
            }
        }

        return result;


    }

    private Integer makeKey(RoomAttendsEntity e) {

        Integer key = DurationDistributionEnum.getKey(e.getDuration());
        return key;

    }

    private List<UserViewDurationDistributionRspVO> getAllDurationDistribution(UserParamVO reqVO) {
        List<UserViewDurationDistributionRspVO> liveStreamDurationDistribution = getLiveStreamDurationDistribution(reqVO);
        Map<Integer, List<UserViewDurationDistributionRspVO>> listMap = liveStreamDurationDistribution.stream().collect(Collectors.groupingBy(UserViewDurationDistributionRspVO::getKey));
        List<UserViewDurationDistributionRspVO> liveBackDurationDistribution = getLiveBackDurationDistribution(reqVO);
        Map<Integer, List<UserViewDurationDistributionRspVO>> collect = liveBackDurationDistribution.stream().collect(Collectors.groupingBy(UserViewDurationDistributionRspVO::getKey));

        List<UserViewDurationDistributionRspVO> result = new ArrayList<>();
        for (int i = 0; i < 9; i++) {
            List<UserViewDurationDistributionRspVO> live = CollectionUtils.isEmpty(listMap.get(i)) ? new ArrayList<>() : listMap.get(i);
            List<UserViewDurationDistributionRspVO> back = CollectionUtils.isEmpty(collect.get(i)) ? new ArrayList<>() : collect.get(i);

            UserViewDurationDistributionRspVO rspVO = new UserViewDurationDistributionRspVO();
            rspVO.setKey(i);
            rspVO.setNum(CollectionUtils.isEmpty(live) ? 0 : live.get(0).getNum()
                    + (CollectionUtils.isEmpty(back) ? 0 : back.get(0).getNum()));
            result.add(rspVO);

        }

        return result;

    }

    @Override
    public NumOfViewersAndOtherInfoRspVO numOfViewersAndOtherInfo(UserParamVO reqVO) {
        validateSixTime(reqVO);
        UserParamVO userParamVO = new UserParamVO();
        String startTime = reqVO.getStartTime();
        String endTime = reqVO.getEndTime();
        endTime = setReqEndTime(endTime);
        userParamVO.setStartTime(startTime);
        userParamVO.setEndTime(endTime);
        Token token = TokenThreadLocal.getToken();
        UserBasicStatisticsRspVO ubsrv ;
        if (!Objects.equals(RoleTypeEnum.PLATFORM_LEVEL.getValue(),token.getRoleType())) {
            String orgCode = token.getOrgCode();
            userParamVO.setOrgCode(orgCode);
        }
        ubsrv = accountForDataMapper.getBasicStatisticsInfo(userParamVO);

        Integer uvCount = Optional.ofNullable(ubsrv.getUvCount()).orElse(0);
        int avgWatchDuration = (uvCount > 0) ?
                Convert.toInt(Math.ceil(ubsrv.getTotalDuration().doubleValue() / ubsrv.getUvCount().doubleValue())) : 0;
        LambdaQueryWrapper<AccountEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AccountEntity::getAccountType, AccountType.WATCHER.getCode())
                .ge(AccountEntity::getCreatedAt,startTime)
                .le(AccountEntity::getCreatedAt,endTime)
        ;
        Integer createAccountCount = accountForDataMapper.selectCount(queryWrapper);
        return NumOfViewersAndOtherInfoRspVO.builder().liveStreamingViewersNum(createAccountCount)
                .avgWatchTime(avgWatchDuration).build();

    }

    @Override
    public List<PlayVolumeTrendRspVO> playVolumeTrend(UserParamVO reqVO) {

        Preconditions.checkArgument(StringUtils.isNotBlank(reqVO.getRoomId()), "room_id 不能为空！");
        validateSixTime(reqVO);

        RoomsEntityDTO roomInfo = roomInnerService.getRoomInfo(reqVO.getRoomId());
        Preconditions.checkArgument(roomInfo != null, "room_id 有误！");
        reqVO.setIlId(roomInfo.getIlId());

        Integer loadOrUnload = roomInfo.getLoadOrUnload();
        List<PlayVolumeTrendRspVO> infoByDay = new ArrayList<>();
        if (loadOrUnload.equals(StatusEnum.OPEN.getValue())) {
            assemblyTime(reqVO, roomInfo);
            infoByDay = accountForDataMapper.getVodInfoByDay(reqVO);
            if (CollectionUtils.isNotEmpty(infoByDay)) {
                for (int i = 0; i < infoByDay.size(); i++) {
                    PlayVolumeTrendRspVO today = infoByDay.get(i);
                    int intValue = 0;
                    if (i - 1 >= 0) {
                        PlayVolumeTrendRspVO before = infoByDay.get(i - 1);
                        BigDecimal todayBig = new BigDecimal(today.getOriginal());
                        BigDecimal beforeBig = new BigDecimal(before.getOriginal());

                        BigDecimal divide = (todayBig.subtract(beforeBig)).divide(beforeBig, 4, RoundingMode.HALF_UP);
                        intValue = divide.multiply(new BigDecimal("100")).intValue();
                    }
                    today.setGrowthRate(intValue);
                }
            }
        }


        return infoByDay;


    }

    @Override
    public Long virtualPv(String roomId) {
        LambdaQueryWrapper<RoomsEntity> roomsEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        roomsEntityLambdaQueryWrapper.eq(RoomsEntity::getRoomId, roomId);
        roomsEntityLambdaQueryWrapper.last(" limit 1");
        RoomsEntity roomInfo = roomMapper.selectOne(roomsEntityLambdaQueryWrapper);
        Integer ilId = roomInfo.getIlId();
        String key = "virtual:connect:count:" + ilId;
        Long count = 0L;
        int randomNumber = getRandomNumber();
        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            count = redisTemplate.opsForValue().increment(key, randomNumber);
        } else {
            count = getRoomWatchUsePV(roomInfo, randomNumber);
            redisTemplate.expire(key, 2, TimeUnit.MINUTES);
        }

        createRoomStatsExpansion(ilId, randomNumber);

        sendColumnVirtualConnectCountMessage(roomInfo, count);

        return count;
    }

    /**
     * 发送虚拟直播间栏目观看数同步消息
     * @param roomInfo
     * @param count
     */
    private void sendColumnVirtualConnectCountMessage(RoomsEntity roomInfo, Long count) {
        JSONObject body = new JSONObject();
        body.put("type", SendMessageTypeEnum.COLUMN_VIRTUAL_CONNECT_COUNT.getType());
        body.put("room_id", roomInfo.getRoomId());
        body.put("column_id", roomInfo.getColumnId());
        body.put("virtual_connect_count", count);
        paasService.sendMessage(roomInfo.getChannelId(), body.toJSONString());
    }

    private void createRoomStatsExpansion(Integer ilId, int randomNumber) {
        RoomStatsExpansion roomStatsExpansion = new RoomStatsExpansion();
        roomStatsExpansion.setIlID(ilId);
        roomStatsExpansion.setExpansionNumber(randomNumber);
        roomStatsExpansion.setCreateTime(new Date());
        roomStatsExpansionMapper.insert(roomStatsExpansion);
    }

    /**
     * 直播间获取存在浮动的用户 pv
     * @param roomInfo 直播间信息
     * @param randomNumber 本次浮动的观看次数
     * @return
     */
    @Nullable
    private Long getRoomWatchUsePV(RoomsEntity roomInfo, int randomNumber) {
        Integer ilId = roomInfo.getIlId();
        String key = "virtual:connect:count:" + ilId;
        Long count = 0L;
        Long pvCountFromStatics = Long.valueOf(getPvCountFromStatics(roomInfo));

        QueryWrapper<RoomStatsExpansion> queryWrapper = Wrappers.query();
        queryWrapper.eq("il_id", ilId);
        Integer selectCount = roomStatsExpansionMapper.selectCount(queryWrapper);
        if (selectCount > 0) {
            queryWrapper.select("SUM(expansion_number) as total");
            List<Map<String, Object>> mapList = roomStatsExpansionMapper.selectMaps(queryWrapper);
            Map<String, Object> objectMap = mapList.get(0);
            Object total = objectMap.get("total");
            if (total == null) {
                total = "0";
            }
            pvCountFromStatics += Long.parseLong(String.valueOf(total));
        }
        Integer cacheLiveExternalChannelViewCount = externalLiveStatsService.getCacheLiveExternalChannelViewCount(ilId);

//            迁移数据中记录的观看次数
        Integer totalNumberOfViews = Optional.ofNullable(roomInfo.getTotalNumberOfViews()).orElse(0);
        count += pvCountFromStatics;
        count += totalNumberOfViews;
        count = redisTemplate.opsForValue().increment(key, count + randomNumber);
        count += cacheLiveExternalChannelViewCount;
        return count;
    }

    @Override
    public PageVO<DpLiveViewDataResponseVO> getDpColumnLiveViewData(UserParamVO reqVO) {
        List<DpLiveViewDataResponseVO> result = getAllDpColumnLiveViewDataListMain(reqVO);
        return getDpLiveViewDataResponseVOPageVO(reqVO.getPage(), reqVO.getPageSize(), result);
    }
    @Override
    public List<DpLiveViewDataResponseVO> getAllDpColumnLiveViewDataListMain(UserParamVO reqVO) {

        String endTime = reqVO.getEndTime();
        String startTime = reqVO.getStartTime();
        String orgCode = "";
        String key = RedisKey.DP_LIVE_VIEW_DATA_LIST_COLUMN+":"+startTime+":"+endTime;
        List<DpLiveViewDataResponseVO> result = null;
        if (redisTemplate.hasKey(key)) {
            Object listData = redisTemplate.opsForValue().get(key);
            if (Objects.nonNull(listData)) {
                result = JSON.parseArray(listData.toString(), DpLiveViewDataResponseVO.class);
            }
        }else{
//            时间范围内的房间总数
            Integer roomCount = getRoomCount(startTime, endTime, orgCode);
            result = liveColumnMapper.selectColumnListRoomCount(reqVO);
            if(CollUtil.isNotEmpty(result)){
                List<DpLiveViewDataResponseVO> viewResult = liveColumnMapper.selectColumnListViewCount(reqVO);
                Map<Integer, DpLiveViewDataResponseVO> columnIdToCountData = viewResult.stream().collect(Collectors.toMap(DpLiveViewDataResponseVO::getId, e -> e, (e1, e2) -> e1));
                BigDecimal roomCountBig = BigDecimal.valueOf(roomCount);
                result = result.stream().map(data->{
                    String liveSessionPercent = "0%";
                    int id = data.getId();
                    DpLiveViewDataResponseVO dpLiveViewDataResponseVO = columnIdToCountData.get(id);
                    dpLiveViewDataResponseVO.setLiveNumber(data.getLiveNumber());
                    BigDecimal liveNumberBig = BigDecimal.valueOf(data.getLiveNumber());
                    if (roomCount>=1) {
                        BigDecimal div = NumberUtil.div(liveNumberBig, roomCountBig).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
                        liveSessionPercent = div.toString()+"%";
                    }
                    dpLiveViewDataResponseVO.setLiveSessionPercent(liveSessionPercent);
                    return dpLiveViewDataResponseVO;
                }).collect(Collectors.toList());
                redisTemplate.opsForValue().set(key,JSON.toJSONString(result),1,TimeUnit.DAYS);
            }
        }
        Integer sortType = reqVO.getSortType();
        SortTypeEnum sortTypeEnum = SortTypeEnum.getSortTypeEnum(sortType,SortTypeEnum.DESC_SORT);
        result = getDpLiveViewDataSortList(sortTypeEnum, result);
        return result;
    }

    /**
     * 对数据进行排序
     * @param sortTypeEnum
     * @param result
     * @return
     */
    private List<DpLiveViewDataResponseVO> getDpLiveViewDataSortList(SortTypeEnum sortTypeEnum, List<DpLiveViewDataResponseVO> result) {
        if (CollUtil.isNotEmpty(result)) {
            Comparator<DpLiveViewDataResponseVO> sortTypeComparator = Comparator.comparing(DpLiveViewDataResponseVO::getLiveNumber).reversed().thenComparing(DpLiveViewDataResponseVO::getSubject);
            if (Objects.equals(SortTypeEnum.ASC_SORT,sortTypeEnum)) {
                sortTypeComparator = Comparator.comparing(DpLiveViewDataResponseVO::getLiveNumber).thenComparing(DpLiveViewDataResponseVO::getSubject);
            }
            result = result.stream().distinct().sorted(sortTypeComparator).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * 对直播观看数据进行分页处理
     * @param page 分页位置
     * @param pageSize 单页显示数据量
     * @param result 数据源
     * @return
     */
    private PageVO<DpLiveViewDataResponseVO> getDpLiveViewDataResponseVOPageVO(Integer page, Integer pageSize, List<DpLiveViewDataResponseVO> result) {
        if (CollUtil.isNotEmpty(result)) {
            int size = result.size();
            int startIndex = (page -1)* pageSize;
            result = result.stream().skip(startIndex).limit(pageSize).collect(Collectors.toList());
            return new PageVO<>(page, pageSize, size, result);
        }else{
            return new PageVO<>(page, pageSize,0,new ArrayList<>());
        }
    }

    private Integer getRoomCount(String startTime, String endTime, String orgCode) {
        LambdaQueryWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(StrUtil.isNotBlank(orgCode),RoomsEntity::getOrgCode, orgCode)
                .ne(RoomsEntity::getColumnId,0)
                .ne(RoomsEntity::getStatus, RoomStatusEnum.TO_BE_BROADCAST.getStatus())
                .eq(RoomsEntity::getLiveRormal, LiveRormalEnum.OFFICIAL_LIVE.getValue());
        queryWrapper.ge(RoomsEntity::getStartTime, startTime)
                .le(RoomsEntity::getStartTime, endTime);
        return roomMapper.selectCount(queryWrapper);
    }

    @Override
    public PageVO<DpLiveViewDataResponseVO> getDpAnchorLiveViewData(UserParamVO reqVO) {
        List<DpLiveViewDataResponseVO> result = getAllDpAnchorLiveViewDataListMain(reqVO);
        return getDpLiveViewDataResponseVOPageVO(reqVO.getPage(), reqVO.getPageSize(), result);
    }

    @Override
    public List<DpLiveViewDataResponseVO> getAllDpAnchorLiveViewDataListMain(UserParamVO reqVO) {
        String endTime = reqVO.getEndTime();
        String startTime = reqVO.getStartTime();
        String orgCode = "";
        String key = RedisKey.DP_LIVE_VIEW_DATA_LIST_ANCHOR+":"+startTime+":"+endTime;
        List<DpLiveViewDataResponseVO> result = null;
        if (redisTemplate.hasKey(key)) {
            Object listData = redisTemplate.opsForValue().get(key);
            if (Objects.nonNull(listData)) {
                result = JSON.parseArray(listData.toString(), DpLiveViewDataResponseVO.class);
            }
        }else{
//            时间范围内的房间总数
            Integer roomCount = getRoomCount(startTime, endTime, orgCode);
            result = anchorRoomRelationMapper.selectAnchorListRoomCount(reqVO);
            if(CollUtil.isNotEmpty(result)){
                List<DpLiveViewDataResponseVO> viewResult = anchorRoomRelationMapper.selectAnchorListViewCount(reqVO);
                Map<String, DpLiveViewDataResponseVO> columnIdToCountData = viewResult.stream().collect(Collectors.toMap(DpLiveViewDataResponseVO::getUserCode, e -> e, (e1, e2) -> e1));
                BigDecimal roomCountBig = BigDecimal.valueOf(roomCount);
                result = result.stream().map(data->{
                    String liveSessionPercent = "0%";
                    String userCode = data.getUserCode();
                    DpLiveViewDataResponseVO dpLiveViewDataResponseVO = columnIdToCountData.get(userCode);
                    dpLiveViewDataResponseVO.setLiveNumber(data.getLiveNumber());
                    BigDecimal liveNumberBig = BigDecimal.valueOf(data.getLiveNumber());
                    if (roomCount>=1) {
                        BigDecimal div = NumberUtil.div(liveNumberBig, roomCountBig).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP);
                        liveSessionPercent = div.toString()+"%";
                    }
                    dpLiveViewDataResponseVO.setLiveSessionPercent(liveSessionPercent);
                    return dpLiveViewDataResponseVO;
                }).collect(Collectors.toList());
                redisTemplate.opsForValue().set(key,JSON.toJSONString(result),1,TimeUnit.DAYS);
            }
        }
        Integer sortType = reqVO.getSortType();
        SortTypeEnum sortTypeEnum = SortTypeEnum.getSortTypeEnum(sortType,SortTypeEnum.DESC_SORT);
        result = getDpLiveViewDataSortList(sortTypeEnum, result);
        return result;
    }

    @Override
    public List<SelectTimeIntervalOptionsVO> getSelectTimeIntervalOptions() {
        List<SelectTimeIntervalOptionsVO> result ;
        LocalDate today = LocalDate.now();
        String todayDate = today.format(DateTimeFormatter.ISO_LOCAL_DATE);
        result = Arrays.stream(SelectTimeIntervalOptionsEnum.values()).sorted(Comparator.comparing(SelectTimeIntervalOptionsEnum::getIndex))
                .map(timeOptions->{
                    SelectTimeIntervalOptionsVO data = new SelectTimeIntervalOptionsVO();
                    data.setSubject(timeOptions.getDescription());
                    data.setStartDate(timeOptions.getStartTime());
                    data.setEndDate(todayDate);
                    return data;
                }).collect(Collectors.toList());
        return result;
    }

    private int getPvCountFromStatics(RoomsEntity room) {
        UserParamVO reqVO = new UserParamVO();
        reqVO.setIlId(room.getIlId());

        String key = MessageFormat.format("{0}:{1}", CACHE_SELECTEDVIDEOLIST_GETPVCOUNTFROMSTATICS, JSON.toJSONString(reqVO));
        Object o = redisTemplate.opsForValue().get(key);
        if (o != null) {
            return Integer.parseInt(o.toString());
        }

        UserBasicStatisticsRspVO ubsrv = accountForDataMapper.getBasicStatisticsInfo(reqVO);
        int pvCount = (ubsrv.getPvCount() != null && ubsrv.getPvCount() > 0) ? ubsrv.getPvCount() : 0;

        UserBasicStatisticsRspVO ubsrvVod = accountForDataMapper.getVodBasicStatisticsInfo(reqVO);
        pvCount += (ubsrvVod.getPvCount() != null && ubsrvVod.getPvCount() > 0) ? ubsrvVod.getPvCount() : 0;

        redisTemplate.opsForValue().set(key, pvCount, 2, TimeUnit.SECONDS);
        return pvCount;
    }

    private int getRandomNumber() {
        int min = 5;
        int max = 10;

        Random random = new Random();

        return random.nextInt(max - min + 1) + min;
    }

    private void assemblyTime(UserParamVO reqVO, RoomsEntityDTO roomInfo) {
        LocalDateTime start = roomInfo.getLoadOrUnloadAt();
        LocalDateTime end = start.plusDays(30);

        reqVO.setStartTime(LocalDateTimeUtil.format(start, DatePattern.NORM_DATE_PATTERN));
        reqVO.setEndTime(LocalDateTimeUtil.format(end, DatePattern.NORM_DATE_PATTERN));
    }


    /**
     * 拼装结果集
     *
     * @param resultVO
     * @param allFlag  全部标记位
     * @return
     */
    private List<DpWatchTimeTopRspVO> assemblyResult(List<DpWatchTimeTopRspVO> resultVO, boolean allFlag) {
        List<DpWatchTimeTopRspVO> result = new ArrayList<>(24);

        if (!allFlag) {
            Map<Integer, Integer> resultMap = new HashMap<>(resultVO.size());
            if (CollectionUtils.isNotEmpty(resultVO)) {
                resultMap = resultVO.stream().collect(Collectors.toMap(DpWatchTimeTopRspVO::getBtime, DpWatchTimeTopRspVO::getOriginal));
            }
            for (int i = 0; i < 24; i++) {
                result.add(DpWatchTimeTopRspVO.builder().btime(i).original(resultMap.get(i) == null ? 0 : resultMap.get(i)).build());
            }
        } else {
            result.addAll(resultVO);
        }
        return result;
    }

    private List<DpWatchTimeTopRspVO> getAllDpWatchTimeTop(UserParamVO reqVO) {
        List<DpWatchTimeTopRspVO> liveStreamDpWatchTimeTop = getLiveStreamDpWatchTimeTop(reqVO);
        Map<Integer, Integer> liveStreamMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(liveStreamDpWatchTimeTop)) {
            liveStreamMap = liveStreamDpWatchTimeTop.stream().collect(Collectors.toMap(DpWatchTimeTopRspVO::getBtime, DpWatchTimeTopRspVO::getOriginal));
        }

        List<DpWatchTimeTopRspVO> liveBackDpWatchTimeTop = getLiveBackDpWatchTimeTop(reqVO);
        Map<Integer, Integer> liveBackMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(liveBackDpWatchTimeTop)) {
            liveBackMap = liveBackDpWatchTimeTop.stream().collect(Collectors.toMap(DpWatchTimeTopRspVO::getBtime, DpWatchTimeTopRspVO::getOriginal));
        }
        List<DpWatchTimeTopRspVO> result = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            int liveStream = liveStreamMap.get(i) == null ? 0 : liveStreamMap.get(i);
            int liveBack = liveBackMap.get(i) == null ? 0 : liveBackMap.get(i);
            result.add(DpWatchTimeTopRspVO.builder().btime(i).original(liveStream + liveBack).build());
        }

        return result;

    }

    /**
     * 直播回放
     */
    private List<DpWatchTimeTopRspVO> getLiveBackDpWatchTimeTop(UserParamVO reqVO) {
        return accountForDataMapper.getLiveBackDpWatchTimeTop(reqVO);
    }

    /**
     * 直播中
     */
    private List<DpWatchTimeTopRspVO> getLiveStreamDpWatchTimeTop(UserParamVO reqVO) {
        return accountForDataMapper.getLiveStreamDpWatchTimeTop(reqVO);
    }

    private void roomCheck(UserParamVO reqVO) {
        if (reqVO.getIlId() == null || StringUtils.isBlank(reqVO.getIlId().toString())) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        RoomsEntityDTO ilInfo = roomInnerService.getRoomInfoByIlId(reqVO.getIlId().toString());
        if (null == ilInfo) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
    }

    public String setReqEndTime(String endTime) {
        if (StringUtils.isNotBlank(endTime)) {
            if (endTime.contains(ConstStr.TIME_ZERO)) {
                endTime = endTime.replace(ConstStr.TIME_ZERO, ConstStr.TIME_FULL);
            } else {
                endTime = endTime + " " + ConstStr.TIME_FULL;
            }
        }
        return endTime;
    }

}